package com.yhb.channel.impl.BJCJ;

import com.yhb.channel.ChannelConstant;
import com.yhb.channel.FlowService;
import com.yhb.channel.dao.flow.ExecutionFlow;
import com.yhb.channel.impl.BJCJ.http.BJCJClient;
import com.yhb.channel.impl.BJCJ.http.Request.WithdrawQueryRequest;
import com.yhb.channel.impl.BJCJ.http.Response.WithdrawQueryResponse;
import com.yhb.channel.provider.INotifyProvider;
import com.yhb.channel.provider.IUtilProvider;
import com.yhb.channel.utils.ChannelJSONUtil;
import com.yhb.channel.utils.ChannelLogger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

@Service
public class BJCJAsyncService {

    private static ChannelLogger logger;

    @Qualifier("tradeService")
    @Autowired
    private INotifyProvider iNotifyProvider;

    @Autowired
    private BJCJClient bjcjClient;

    @Autowired
    private IUtilProvider iUtilProvider;

    @Autowired
    private FlowService flowService;

    @PostConstruct
    private void init() {
        logger = new ChannelLogger(BJCJChannel.CHANNEL_BASE_NAME, BJCJException.class, iUtilProvider);
    }

    @Async
    public void asyncOrderStatusNotify(ExecutionFlow flow, INotifyProvider.OrderStatus status, int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        iNotifyProvider.orderStatusNotify(flow, status);
    }

    @Async
    public void asyncOrderStatusNotify(ExecutionFlow flow, INotifyProvider.OrderStatus status) {
        asyncOrderStatusNotify(flow, status, 1000);
    }

    @Async
    public void pollingUpRemitResult(String userId, String reqFlowNo, String channelCode, ExecutionFlow remitFlow) {
        // 轮询逻辑
        for (int i = 1; i < ChannelConstant.MAX_POLLING_TIMES_FOR_REMIT_AND_PAY; i++) {
            try {
                Thread.sleep(ChannelConstant.POLLING_TIME_INTERVAL_FOR_REMIT_AND_PAY);
            } catch (InterruptedException e) {
                logger.fail(BJCJConstant.INNER_ERROR, channelCode + "轮询错误", e);
            }
            logger.info("轮询ing... reqFlowNo:" + reqFlowNo);
            // 调用查询接口
            WithdrawQueryRequest withdrawQueryRequest = WithdrawQueryRequest.builder()
                    .build();
            withdrawQueryRequest.setReqFlowNo(reqFlowNo);
            withdrawQueryRequest.setMerId(userId);
            withdrawQueryRequest.setChannelCode(channelCode);
            WithdrawQueryResponse withdrawQueryResponse = bjcjClient.http(WithdrawQueryRequest.action
                    , withdrawQueryRequest, WithdrawQueryResponse.class, channelCode);
            // 检查查询结果
            if (!withdrawQueryResponse.isSuccess() || !withdrawQueryResponse.getData().isSuccess()) {
                // 这种情况一般remit也是失败了
                // 而且不管失败不失败 这里都要标失败 防止OrderStatus保持INITIALIZED
                // 导致下次轮询 依旧查询失败
                flowService.fail(remitFlow);
                iNotifyProvider.orderStatusNotify(remitFlow,
                        INotifyProvider.OrderStatus.FAILED); // 通知业务失败

                logger.fail(BJCJConstant.INNER_ERROR, channelCode + "async轮询remit结果失败：\n"
                        + withdrawQueryResponse.getMessage() + "\n" + withdrawQueryResponse.getData().getMessage());
                return;
            } else if (!withdrawQueryResponse.orderStatusIsPending()) { // 结果不是pending
                if (withdrawQueryResponse.orderStatusIsSucceed()) { // 结果ok
                    logger.info("reqFlowNo: " + reqFlowNo + " success async");
                    flowService.success(remitFlow);
                    iNotifyProvider.orderStatusNotify(remitFlow,
                            INotifyProvider.OrderStatus.SUCCEED); // 通知业务成功
                } else if(withdrawQueryResponse.orderStatusIsFailed()) { // 结果fail
                    logger.info("reqFlowNo: " + reqFlowNo + " fail async");
                    flowService.fail(remitFlow);
                    iNotifyProvider.orderStatusNotify(remitFlow,
                            INotifyProvider.OrderStatus.FAILED); // 通知业务失败
                } else {
                    logger.fail(BJCJConstant.INNER_ERROR, "通道返回数据异常: "
                            + ChannelJSONUtil.toJson(withdrawQueryResponse));
                }
                return;
            } else {
                logger.info("reqFlowNo: " + reqFlowNo + " pending");
            }
        }
    }
}
